/* arch/x86_64/boot/setup.S 
 * 
 * This file is part of xnix. 
 * 
 * XNIX is free software: you can redistribute it and/or modify 
 * it under the terms of the GNU General Public License as published by 
 * the Free Software Foundation, either version 3 of the License, or 
 * (at your option) any later version. 
 * 
 * XNIX is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 * GNU General Public License for more details. 
 * 
 * You should have received a copy of the GNU General Public License 
 * along with XNIX. If not, see <https://www.gnu.org/licenses/>
 */ 




.code16


/* switch to the protected-mode, and to real system (XNIX Loader) */

.globl _start

_start:	xorw %ax, %ax

	movw %ax, %ds
	movw %ax, %es
	movw %ax, %ss

	/* yeah, we should move it again. */
	movw $0x7e00, %di
	movw $0x8000, %si

	movw $512, %cx

	cld
	rep
	movsb

	movw $0x7c00, %sp

	ljmp $0, $real_start

real_start:
	/* open a20 */
	cli

	inb $0x92, %al
	orb $0x02, %al
	outb %al, $0x92

	/* setup idt and gdt */
	lgdt gdt32_descr

	movl %cr0, %eax
	orl $1, %eax

	/* that's it! */
	movl %eax, %cr0

	/* setup paging */

	movl $0, %edi
	movl $512, %ecx
	xorl %eax, %eax

	cld

rsetpt:	rep
	stosl

	movl $0x00001003, 0

/* and also map it to 0xffff8000xxxxxxxx */

	movl $0x00001003, 0x800

	movl $0x00002003, 0x1000
	movl $0x00003003, 0x2000
	
	movl $0x3000, %edi
	movl $0x00000083, %eax

	cld

rsetp:	/* no! not this! stosl only sets 4bytes, but 
	 * the pt is 8-bytes! 
	 * 
	 * stosl
	 */
	movl %eax, (%edi)
	movl $0, 4(%edi)

	addl $8, %edi

	addl $4096, %eax

	cmpl $0x800000, %eax
	jbe rsetp

/*	we can't do those like we did in i386/, because
	we can't enable paging before lm. 
	xorl %eax, %eax
	movl %eax, %cr3

	movl %cr0, %eax
	orl $0x80000000, %eax
	movl %eax, %cr0*/

	ljmp $0x08, $init_prot


.code32

init_prot:
	movl $0x10, %eax

	movl %eax, %ds
	movl %eax, %es
	movl %eax, %fs
	movl %eax, %gs

	movl %eax, %ss

/* and then setup the long-mode */

	lgdt gdt64_descr

	/* pae and pge */
	movl $0x000000a0, %eax
	movl %eax, %cr4

	xorl %eax, %eax
	movl %eax, %cr3

	movl $0xc0000080, %ecx
	rdmsr

	orl $0x100, %eax
	wrmsr

	/* setup paging here */

	movl %cr0, %eax

/* and re-set the pe too */

	orl $0x80000001, %eax

	movl %eax, %cr0

	ljmp $0x08, $init_lm

.code64

init_lm:
	movq $0x10, %rax
	
	movq %rax, %ds
	movq %rax, %es
	movq %rax, %fs
	movq %rax, %gs

	movq %rax, %ss

	movq $1048576, %rdi
	movq $0x8400, %rsi

	movq $65536, %rcx

	cld

	rep 
	movsq

	pushq $1048576

	retq


.globl gdt32

gdt32:	.long 0x00000000, 0x00000000
	.long 0x0000ffff, 0x00cf9a00
	.long 0x0000ffff, 0x00cf9200


.globl gdt32_descr

gdt32_descr:
	.word . - gdt32
	.long gdt32


.globl gdt64

gdt64:
	.quad 0x0000000000000000
	.quad 0x0020980000000000
	.quad 0x0000920000000000

gdt64_descr:
	.word . - gdt64
	.long gdt64


